package jupp;

import java.io.*;

import java.util.*;
import java.util.prefs.BackingStoreException;
import java.util.concurrent.atomic.AtomicInteger;

public class CompressedStorage
{
	private static class Lump implements Serializable
	{
		/**
		* static class member is initialized each time JVM starts,
		* make sure it's up to date by looking for a previous value in
		* JuppMap. Note that the method used here is not Thread-safe
		*/
		private final static String ID_KEY = "atomic.count";
		private static final JuppMap<AtomicInteger> JUPP_MAP_ID = initIDMap();
		private static final AtomicInteger atomiCount = initLumpID();
		public static void destroy() throws BackingStoreException
		{
			JUPP_MAP_ID.destroy();
		}
		private static JuppMap<AtomicInteger> initIDMap()
		{
			try
			{
				return new JuppMap<AtomicInteger>("jupp.tests.storage.gzip.lump.id");
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			System.out.println("Failed to init lump JuppMap");
			return null;
		}
		private static AtomicInteger initLumpID()
		{
			try
			{
				AtomicInteger ai = JUPP_MAP_ID.get(ID_KEY);
				if (ai == null)
					ai = new AtomicInteger(0);
				return ai;
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			System.out.println("Failed to init id JuppMap");
			return null;
		}
		public final static long serialVersionUID = 42l;
		private final int key = atomiCount.getAndIncrement();
		private String bigString;
		private Lump() throws IOException, ClassNotFoundException, java.util.prefs.BackingStoreException
		{
			JUPP_MAP_ID.put(ID_KEY, atomiCount);
			bigString = ".";
			for (int i = 20; i > 0; i--)
				bigString += i + bigString;
			bigString = key + bigString;
		}
		public String getKey()
		{ return Integer.toString(key); }
		public String toString()
		{
			return bigString.substring(0, 8) + "...";
		}
	}
	public static void main(String[] args) throws Exception
	{
		JuppMapGZIP<Lump> lumps = new JuppMapGZIP<Lump>("jupp.tests.storage.gzip.lumps");

		Scanner scanner = new Scanner(System.in);
		while (true)
		{
			System.out.println("(L)ist, (N)ew, (C)lear, (D)estroy or (Q)uit");
			String choice = scanner.nextLine();
			switch (choice.toUpperCase().charAt(0))
			{
				case 'L':
					System.out.println("List...");
					long timeNow = System.nanoTime();
					Set<Map.Entry<String, Lump>> setLumpEntries = lumps.entrySet();
					System.out.println("Time to entrySet is " + (System.nanoTime() - timeNow) / 1000000.0 + "ms");
					for (Map.Entry<String, Lump> entry : lumps.entrySet())
					{
						timeNow = System.nanoTime();
						Lump l = entry.getValue();
						timeNow = System.nanoTime() - timeNow;
						System.out.println(entry.getKey() + " -> " + lumps.get(entry.getKey()) + ", time to getValue() is " + timeNow / 1000000.0 + "ms");
					}
					System.out.println("List complete");
					break;
				case 'N':
					{
						Lump l = new Lump();
						lumps.put(l.getKey(), l);
					}
					break;
				case 'C':
					lumps.clear();
					System.out.println("Cleared.");
					break;
				case 'D':
					lumps.destroy();
					Lump.destroy();
					System.out.println("Destroyed.");
					System.exit(0);
					break;
				case 'Q':
					System.out.println("Bye!");
					System.exit(0);
					break;
				default:
					System.out.println("Something wrong with '" + choice + "'");
			} // switch user choice
		}
	}
}
